package database;

import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;

import com.itany.mall.constant.UserRoleEnum;
import com.itany.mall.entity.MallData;
import com.itany.mall.entity.ProductType;
import com.itany.mall.entity.User;

// 基于IO流实现数据持久化
public class Database02 {

	public static final String USERS_DIR = "./users";
	public static final String USER_SUFFIX = ".user";

	public static final String PRODUCT_TYPE_DIR = "./producttypes";
	public static final String PRODUCT_TYPE_SUFFIX = ".producttype";

	public static final String PRODUCT_DIR = "./products";
	public static final String PRODUCT_SUFFIX = ".product";

	public static final String ORDER_DIR = "./orders";
	public static final String ORDER_SUFFIX = ".order";

	public static final String ORDER_DETAIL_DIR = "./orderdetails";
	public static final String ORDER_DETAIL_SUFFIX = ".detail";

	// 各存储目录下, 分别有一个主键自增长记录文件, 都叫 "primary_key"
	public static final String PRIMARY_KEY = "primary_key";

	// 初始化用户模拟数据
	private static void initUsers() throws IOException {
		// 初始化存储目录, 根据结果决定要不要创建模拟数据
		if (initDir(USERS_DIR, USER_SUFFIX)) {
			// 需要创建模拟数据
			User admin = new User("admin", "123456", "13000000000", "admin@user.com",
					UserRoleEnum.ADMIN.getRoleCode());
			admin.setId(autoIncrement(USERS_DIR));
			saveMallData(USERS_DIR, admin, USER_SUFFIX);

			User alice = new User("alice", "123456", "13000000001", "alice@user.com",
					UserRoleEnum.NORMAL.getRoleCode());
			alice.setId(autoIncrement(USERS_DIR));
			saveMallData(USERS_DIR, alice, USER_SUFFIX);

			User tom = new User("tom", "123456", "13000000002", "tom@user.com",
					UserRoleEnum.NORMAL.getRoleCode());
			tom.setId(autoIncrement(USERS_DIR));
			saveMallData(USERS_DIR, tom, USER_SUFFIX);
		}
	}

	// 初始化商品类型模拟数据
	private static void initProductTypes() throws IOException {
		// 初始化存储目录, 根据结果决定要不要创建模拟数据
		if (initDir(PRODUCT_TYPE_DIR, PRODUCT_TYPE_SUFFIX)) {
			ProductType t1 = new ProductType("食品");
			t1.setId(autoIncrement(PRODUCT_TYPE_DIR));
			saveMallData(PRODUCT_TYPE_DIR, t1, PRODUCT_TYPE_SUFFIX);

			ProductType t2 = new ProductType("饮料");
			t2.setId(autoIncrement(PRODUCT_TYPE_DIR));
			saveMallData(PRODUCT_TYPE_DIR, t2, PRODUCT_TYPE_SUFFIX);

			ProductType t3 = new ProductType("日用品");
			t3.setId(autoIncrement(PRODUCT_TYPE_DIR));
			saveMallData(PRODUCT_TYPE_DIR, t3, PRODUCT_TYPE_SUFFIX);
		}
	}

	public static boolean initDir(String dir, String suffix) {
		// 如果存储目录不存在, 创建目录
		File mallDataDir = new File(dir);
		if (!mallDataDir.exists()) {
			mallDataDir.mkdirs();
		}
		// 存储目录存在, 但没有用户数据
		// 由于存储目录下, 除了用户信息文件, 还有主键文件
		// 获取目录下文件时, 通过过滤器, 只获取用户信息文件
		File[] mallDatas = mallDataDir.listFiles(new FileFilter() {
			@Override
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(suffix);
			}
		});
		if (mallDatas != null && mallDatas.length > 0) {
			return false;
		}

		return true;
	}

	// 保存用户模拟数据
	public static void saveMallData(String dir, MallData mallData, String suffix) {
		try (ObjectOutputStream oos = new ObjectOutputStream(
				new FileOutputStream(new File(dir, mallData.getId() + suffix)));) {
			oos.writeObject(mallData);
			oos.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// ID自增长
	public static Long autoIncrement(String dir) throws IOException {
		File idFile = new File(dir, PRIMARY_KEY);

		// 如果主键文件不存在, 则创建文件, 并写入1
		if (!idFile.exists()) {
			idFile.createNewFile();
			FileWriter w = new FileWriter(idFile);
			w.write("1");
			w.flush();
			w.close();
			return 1L;
		}

		// 如果主键文件存在, 则读取文件中所记录的当前id自增长值
		// +1后, 写回到文件中并return
		// 要对同一个文件进行读写, 需要使用RandomAccessFile
		RandomAccessFile raf = new RandomAccessFile(idFile, "rw");
		String str = raf.readLine();
		long id = Long.parseLong(str);
		id++;
		raf.seek(0);
		raf.write(String.valueOf(id).getBytes());
		return id;
	}

	public static void init() {
		try {
			initUsers();
			initProductTypes();
			initDir(PRODUCT_DIR, PRODUCT_SUFFIX);
			initDir(ORDER_DIR, ORDER_SUFFIX);
			initDir(ORDER_DETAIL_DIR, ORDER_DETAIL_SUFFIX);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("模拟数据创建失败, 程序中没有模拟数据可用");
		}
	}

}
